package com.bruce.spring.http.service.controller;


import com.bruce.spring.http.service.cgroup.CgroupV1ProviderWithChannel;
import com.bruce.spring.http.service.cgroup.CgroupV1ProviderWithFiles;
import com.bruce.spring.http.service.cgroup.CgroupV2ProviderWithChannel;
import com.bruce.spring.http.service.cgroup.CgroupV2ProviderWithFiles;
import com.bruce.spring.http.service.cgroup.ContainerCpuMonitor;
import com.bruce.spring.http.service.cgroup.CpuUsageProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

/**
 * @author bruce 2025/10/15 17:19
 */
@Slf4j
@RestController
@RequestMapping("cpu")
public class CpuController {

    ContainerCpuMonitor cpuMonitor;

    CpuUsageProvider cgroupProviderWithChannel;
    CpuUsageProvider cgroupProviderWithFiles;

    public CpuController() throws IOException {
        cpuMonitor = ContainerCpuMonitor.getInstance();
        cpuMonitor.startMonitoring(500);

        if (cpuMonitor.isCgroupV2()) {
            cgroupProviderWithChannel = new CgroupV2ProviderWithChannel();
            cgroupProviderWithFiles = new CgroupV2ProviderWithFiles();
        } else {
            cgroupProviderWithChannel = new CgroupV1ProviderWithChannel();
            cgroupProviderWithFiles = new CgroupV1ProviderWithFiles();
        }
    }


    @GetMapping("cpuUsage")
    public String cpuUsage2() {
        boolean isCgroupV2 = cpuMonitor.isCgroupV2();
        try {
            double cpuUsage = cpuMonitor.getCurrentCpuUsage();
            double cpuUsage2 = cpuMonitor.getCurrentCpuUsage2();
            String s = "";
            if (isCgroupV2) {
                s = "v2 cpuUsage: " + cpuUsage + "%" + " cpuUsage2: " + cpuUsage2 + "%";
            } else {
                s = "v1 cpuUsage: " + cpuUsage + "%" + " cpuUsage2: " + cpuUsage2 + "%";
            }
            log.info(s);
            return s;
        } catch (Exception ex) {
            log.error("执行异常:", ex);
            return "执行异常:" + ex.getMessage();
        }
    }

    @GetMapping("cpuTime")
    public String cpuTime() {
        try {
            boolean isCgroupV2 = cpuMonitor.isCgroupV2();
            double cpuTime = cpuMonitor.getCurrentCpuTime();
            String s = "";
            if (isCgroupV2) {
                s = "v2 cpuTime: " + cpuTime;
            } else {
                s = "v1 cpuTime: " + cpuTime;
            }
            log.info(s);
            return s;
        } catch (Exception ex) {
            log.error("执行异常:", ex);
            return "执行异常:" + ex.getMessage();
        }
    }

    @GetMapping("costTimeAll")
    public String cpuTimeCgroupCpuReader(Integer count) {
        String s1 = cpuTimeCgroupCpuReader(count, "fileReader");
        String s2 = cpuTimeCgroupCpuReader(count, "files");
        String s = cpuTimeCgroupCpuReader(count, "channel");
        System.out.println();
        return s1 + "  fileReader \n<br>" + s2 + "  files \n<br>" + s + "  channel";
    }

    // 统计连续访问指定次数耗时
    @GetMapping("costTime")
    public String cpuTimeCgroupCpuReader(@RequestParam(defaultValue = "500") Integer count,
                                         @RequestParam(defaultValue = "channel") String type) {
        CpuUsageProvider cgroupCpuReader;
        if (type.equals("files")) {
            cgroupCpuReader = cgroupProviderWithFiles;
        } else {
            cgroupCpuReader = cgroupProviderWithChannel;
        }

        long startMs = System.currentTimeMillis();
        long startNs = System.nanoTime();
        long startCpuTimeNs = 0;
        long endCpuTimeNs = 0;
        for (int i = 0; i < count; i++) {
            try {
                long cpuTime = cgroupCpuReader.getCurrentCpuTime();
                if (i == 0) {
                    startCpuTimeNs = cpuTime;
                }
                if (i == count - 1) {
                    endCpuTimeNs = cpuTime;
                }
            } catch (Exception ex) {
                log.error("执行异常:", ex);
            }
        }
        long containerCpuTime = endCpuTimeNs - startCpuTimeNs;
        long jvmTimeMs = System.currentTimeMillis() - startMs;
        long jvmTimeNs = System.nanoTime() - startNs;

        // 拼接字符串返回（格式：容器CPU耗时, JVM毫秒耗时, JVM纳秒耗时）
        String s = "containerCpuTime: " + containerCpuTime + "ns, jvmTimeMs: " + jvmTimeMs + "ms, jvmTimeNs: " + jvmTimeNs + "ns";
        log.info("{} , {}", cgroupCpuReader, s);
        return s;
    }


}
